﻿using CqBuiltinService.Extensions;
using CqBuiltinService.Options;
using CqCore.Exception;
using CqCore.Logging;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Text;
using System.Threading.Tasks;

namespace CqBuiltinService.Requests
{
    public class ExceptionTrackMiddleware
    {
        private readonly RequestDelegate next;
        private readonly ILogRecorder logger;
        private readonly RequestOption options;

        public ExceptionTrackMiddleware(RequestDelegate next, ILogRecorder<ExceptionTrackMiddleware> logger, IOptions<RequestOption> options)
        {
            this.next = next;
            this.logger = logger;
            this.options = options.Value;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await next(context);
            }
            catch (Exception ex)
            {
                var data = new EventData
                {
                    Type = $"[{context.Request.Method}]{context.Request.Path.Value}",
                    Message = ex.GetBaseException().Message,
                    Labels = {
                        ["TraceId"] = context.TraceIdentifier,
                        ["Method"] = context.Request.Method,
                        ["Path"] = context.Request.Path.Value,
                        ["Query"] = context.Request.QueryString.Value,
                        ["Content"] = context.Request.Body.ToText(),
                        ["StackTrace"] = ex.StackTrace
                    }
                };

                logger.Fatal(data);

                if (ex.Message.Contains(BadRequstKey.Key))
                    context.Response.StatusCode = 400;
                else
                    context.Response.StatusCode = 500;
                context.Response.ContentType = "application/json";

                if (options.Debug)
                {
                    await context.Response.WriteAsync(JsonConvert.SerializeObject(data), Encoding.UTF8);
                }
                else
                {
                    if (!ex.Message.Contains(BadRequstKey.Key))
                        await context.Response.WriteAsync("程序猿向你抛出一个异常!", Encoding.UTF8);
                    else
                        await context.Response.WriteAsync(ex.Message.Replace(BadRequstKey.Key, ""), Encoding.UTF8);
                }
            }
        }
    }

    public static class ExceptionRecordMiddlewareExtensions
    {
        public static IApplicationBuilder UseBuiltinExceptionTracing(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ExceptionTrackMiddleware>();
        }
    }
}
